package cn.net.shuxing.yifu.common.service;

import cn.net.shuxing.yifu.common.bean.CashWallet;
import cn.net.shuxing.yifu.common.bean.OpenPriceHistory;
import cn.net.shuxing.yifu.common.bean.ShareholderBuyGrantHistory;
import cn.net.shuxing.yifu.common.bean.ShareholderCoinGrantHistory;
import cn.net.shuxing.yifu.common.constant.*;
import cn.net.shuxing.yifu.common.dto.BaseDto;
import cn.net.shuxing.yifu.common.dto.WalletBuyGrantHistoryDto;
import cn.net.shuxing.yifu.common.mapper.ShareholderBuyGrantHistoryMapper;
import cn.net.shuxing.yifu.common.util.CommonExample;
import cn.net.shuxing.yifu.common.util.LocalDateTimeUtil;
import cn.net.shuxing.yifu.common.util.LocalTimeUtil;
import cn.net.shuxing.yifu.common.util.TimeExample;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.swing.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class ShareholderBuyGrantHistoryService extends HistoryService<ShareholderBuyGrantHistory, ShareholderBuyGrantHistoryMapper> {

    @Autowired
    private UserDealHistoryService userDealHistoryService;

    @Autowired
    private ShareholderCoinGrantHistoryService shareholderCoinGrantHistoryService;

    @Autowired
    private UserCapitalService userCapitalService;

    @Autowired
    private CashWalletService cashWalletService;

    @Autowired
    private OpenPriceHistoryService openPriceHistoryService;

    public List<ShareholderBuyGrantHistory> getTodayByCoinTypeIdAndType(Integer coinTypeId, Integer type) {
        TimeExample example = new TimeExample(ShareholderBuyGrantHistory.class);
        example.equals("coinTypeId", coinTypeId);
        example.equals("type", type);
        Example.Criteria criteria = example.getCriteria();
        criteria.andGreaterThanOrEqualTo("createTime", LocalDateTimeUtil.getToday());
        example.and(criteria);
        return getsByExample(example);
    }

    public List<ShareholderBuyGrantHistory> getsByCoinTypeIdAndType(Integer coinTypeId, Integer type) {
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("coinTypeId", coinTypeId);
        example.equals("type", type);
        return getsByExample(example);
    }

    public ShareholderBuyGrantHistory getsByCoinTypeIdAndType(Integer grantId) {
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("grantId", grantId);
        return getByExample(example);
    }

    public BigDecimal getTodayHaveDivdends(Integer coinTypeId) {
        List<ShareholderCoinGrantHistory> todaySysList = shareholderCoinGrantHistoryService.getTodayByCoinTypeIdAndType(coinTypeId, Type.ALIVECOIN);
        BigDecimal todayAliveCount = new BigDecimal(0);
        ArrayList<Integer> todayIdList = new ArrayList<>();
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : todaySysList) {
            Integer id = shareholderCoinGrantHistory.getId();
            todayAliveCount = todayAliveCount.add(shareholderCoinGrantHistory.getCount());
            todayIdList.add(id);
        }
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        Example.Criteria criteria = example.getCriteria();
        criteria.andGreaterThanOrEqualTo("createTime", LocalDateTimeUtil.createLocalDateTime(LocalDate.now(), LocalTimeUtil.createLocalTimeInZero()));
        criteria.andNotIn("grantId", todayIdList);
        example.and(criteria);
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExample(example);
        for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
            todayAliveCount = todayAliveCount.add(shareholderBuyGrantHistory.getCount());
        }
        return todayAliveCount;
    }

    public BigDecimal getTotalHaveDivdends(Integer coinTypeId) {
        List<ShareholderCoinGrantHistory> todaySysList = shareholderCoinGrantHistoryService.getsByCoinTypeIdAndType(coinTypeId, Type.ALIVECOIN);
        BigDecimal todayAliveCount = new BigDecimal(0);
        ArrayList<Integer> todayIdList = new ArrayList<>();
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : todaySysList) {
            Integer id = shareholderCoinGrantHistory.getId();
            todayAliveCount = todayAliveCount.add(shareholderCoinGrantHistory.getCount());
            todayIdList.add(id);
        }
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        Example.Criteria criteria = example.getCriteria();
        if (todayIdList != null && !todayIdList.isEmpty())
            criteria.andNotIn("grantId", todayIdList);
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExample(example);
        if (shareholderBuyGrantHistories == null || shareholderBuyGrantHistories.isEmpty()) {
            return todayAliveCount;
        } else {
            for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                todayAliveCount = todayAliveCount.add(shareholderBuyGrantHistory.getCount());
            }
            return todayAliveCount;
        }


    }

    public BigDecimal getTotalHaveDivdends(Integer coinTypeId,Integer userId) {
        List<ShareholderCoinGrantHistory> todaySysList = shareholderCoinGrantHistoryService.getsByCoinTypeIdAndType(coinTypeId, Type.ALIVECOIN);
        BigDecimal todayAliveCount = new BigDecimal(0);
        ArrayList<Integer> todayIdList = new ArrayList<>();
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : todaySysList) {
            Integer id = shareholderCoinGrantHistory.getId();
            todayAliveCount = todayAliveCount.add(shareholderCoinGrantHistory.getCount());
            todayIdList.add(id);
        }
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        Example.Criteria criteria = example.getCriteria();
        if (todayIdList != null && !todayIdList.isEmpty())
            criteria.andNotIn("grantId", todayIdList);
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExample(example);
        if (shareholderBuyGrantHistories == null || shareholderBuyGrantHistories.isEmpty()) {
            return todayAliveCount;
        } else {
            for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                todayAliveCount = todayAliveCount.add(shareholderBuyGrantHistory.getCount());
            }
            return todayAliveCount;
        }

    }

    public BaseDto buy(Integer userId, List<Integer> grantIds, BigDecimal count) {
        /** 计算配币余额是否足够 **/
        grantIds.sort((x, y) -> {
            return x.compareTo(y);
        });
        BigDecimal totalLeftCount = new BigDecimal(0);
        for (Integer grantId : grantIds) {
            ShareholderCoinGrantHistory shareholderCoinGrantHistory = shareholderCoinGrantHistoryService.getByPrimaryKeyWithoutComplete(grantId);
            BigDecimal leftCount = shareholderCoinGrantHistory.getLeftCount();
            totalLeftCount = totalLeftCount.add(leftCount);
        }
        if (totalLeftCount.compareTo(count) < 0)
            return BaseDto.error("购买数量超过所选配币单剩余货币总量");
        for (Integer grantId : grantIds) {
            if (count.compareTo(new BigDecimal(0)) <= 0) {
                return BaseDto.ok("success");
            }
            ShareholderCoinGrantHistory shareholderCoinGrantHistory = shareholderCoinGrantHistoryService.getByPrimaryKeyWithoutComplete(grantId);
            if (shareholderCoinGrantHistory == null)
                return BaseDto.error("此单不存在");
            if (shareholderCoinGrantHistory.getUserId().compareTo(userId) != 0) {
                return BaseDto.error("这不是你的配币");
            }
            BigDecimal leftCount = shareholderCoinGrantHistory.getLeftCount();
            if (leftCount.compareTo(count) < 0) {
                buy(userId, grantId, leftCount);
                count = count.subtract(leftCount);
            } else {
                return buy(userId, grantId, count);
            }
        }
        return BaseDto.ok("success");
    }

    public BaseDto buy(Integer userId, Integer grantId, BigDecimal count) {
        ShareholderCoinGrantHistory shareholderCoinGrantHistory = shareholderCoinGrantHistoryService.getByPrimaryKeyWithoutComplete(grantId);
        if (shareholderCoinGrantHistory == null)
            return BaseDto.error("此单不存在");
        if (shareholderCoinGrantHistory.getUserId().compareTo(userId) != 0) {
            return BaseDto.error("这不是你的配币");
        }
        BigDecimal leftCount = shareholderCoinGrantHistory.getLeftCount();
        if (leftCount.compareTo(count) < 0) {
            return BaseDto.error("该笔配币单余额不足");
        }

        BigDecimal openPrice = openPriceHistoryService.getOpenPrice(shareholderCoinGrantHistory.getCoinTypeId());
        CashWallet cashWallet = cashWalletService.getByUserId(userId);
        if (cashWallet.getCashCount().compareTo(leftCount.multiply(openPrice)) < 0)
            return BaseDto.error("现金钱包余额不足");

        userCapitalService.addAliveCoin(userId, shareholderCoinGrantHistory.getCoinTypeId(), count, UserType.SHAREHOLDER);
        userDealHistoryService.insert(userId, shareholderCoinGrantHistory.getCoinTypeId(), DealType.BUY_COIN_GRANT, DealScene.NONE, count, openPrice, UserType.SHAREHOLDER, shareholderCoinGrantHistory.getOrderKey());
        cashWalletService.reduceCash(userId, count.multiply(openPrice), CashChangeType.CASH_BUY_COIN_GRANT, grantId.toString());
        shareholderCoinGrantHistory.setLeftCount(leftCount.subtract(count));
        shareholderCoinGrantHistoryService.update(shareholderCoinGrantHistory);

        ShareholderBuyGrantHistory shareholderBuyGrantHistory = new ShareholderBuyGrantHistory();
        shareholderBuyGrantHistory.setType(Type.ALIVECOIN);
        shareholderBuyGrantHistory.setUserId(userId);
        shareholderBuyGrantHistory.setGrantId(grantId);
        shareholderBuyGrantHistory.setCount(count);
        shareholderBuyGrantHistory.setCoinTypeId(shareholderCoinGrantHistory.getCoinTypeId());
        shareholderBuyGrantHistory.setSinglePrice(openPrice);
        shareholderBuyGrantHistory.setGrantTime(shareholderCoinGrantHistory.getCreateTime());
        shareholderBuyGrantHistory.setGrantCount(shareholderCoinGrantHistory.getCount());
        shareholderBuyGrantHistory.setOrderKey(shareholderCoinGrantHistory.getOrderKey());
        try {
            insert(shareholderBuyGrantHistory);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BaseDto.ok(shareholderBuyGrantHistory);

    }

    public List<ShareholderBuyGrantHistory> getByUserIdAndCoinType(Integer userId, Integer coinTypeId) {
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("userId", userId);
        example.equals("coinTypeId", coinTypeId);
        example.setOrderByClause("id DESC");
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExampleWithoutComplete(example);
        List<ShareholderCoinGrantHistory> shareholderCoinGrantHistoryList = shareholderCoinGrantHistoryService.getsByUserIdAndCoinType(userId, coinTypeId);
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : shareholderCoinGrantHistoryList) {
            for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                if (shareholderBuyGrantHistory.getGrantId() == shareholderCoinGrantHistory.getId()) {
                    shareholderBuyGrantHistory.setGrantTime(shareholderCoinGrantHistory.getCreateTime());
                    shareholderBuyGrantHistory.setGrantCount(shareholderCoinGrantHistory.getCount());
                }
            }
        }
        return shareholderBuyGrantHistories;
    }

    public List<ShareholderBuyGrantHistory> getByUserIdAndCoinType(Integer userId, Integer coinTypeId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("userId", userId);
        example.equals("coinTypeId", coinTypeId);
        example.setOrderByClause("id DESC");
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExampleWithoutComplete(example);
        List<ShareholderCoinGrantHistory> shareholderCoinGrantHistoryList = shareholderCoinGrantHistoryService.getsByUserIdAndCoinType(userId, coinTypeId);
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : shareholderCoinGrantHistoryList) {
            for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                if (shareholderBuyGrantHistory.getGrantId() == shareholderCoinGrantHistory.getId()) {
                    shareholderBuyGrantHistory.setGrantTime(shareholderCoinGrantHistory.getCreateTime());
                    shareholderBuyGrantHistory.setGrantCount(shareholderCoinGrantHistory.getCount());
                }
            }
        }
        return shareholderBuyGrantHistories;
    }

    public List<WalletBuyGrantHistoryDto> getsWalletBuyGrantHistory(Integer userId, Integer coinTypeId, Integer pageNum, Integer pageSize) {
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("userId", userId);
        example.equals("coinTypeId", coinTypeId);
        example.setOrderByClause("id DESC");
        List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = getsByExampleWithoutComplete(example);
        List<ShareholderCoinGrantHistory> shareholderCoinGrantHistoryList = shareholderCoinGrantHistoryService.getsByUserIdAndCoinType(userId, coinTypeId);
        ArrayList<WalletBuyGrantHistoryDto> list = new ArrayList<>();
        for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : shareholderCoinGrantHistoryList) {
            for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                if (shareholderBuyGrantHistory.getGrantId() == shareholderCoinGrantHistory.getId()) {
                    shareholderBuyGrantHistory.setGrantTime(shareholderCoinGrantHistory.getCreateTime());
                    shareholderBuyGrantHistory.setGrantCount(shareholderCoinGrantHistory.getCount());
                    WalletBuyGrantHistoryDto listDto = new WalletBuyGrantHistoryDto();
                    listDto.setDistributeTime(shareholderCoinGrantHistory.getCreateTime());
                    listDto.setDistributeCount(shareholderBuyGrantHistory.getGrantCount());
                    listDto.setBuyGrantTime(shareholderBuyGrantHistory.getCreateTime());
                    listDto.setBuyGrantCount(shareholderBuyGrantHistory.getCount());
                    list.add(listDto);
                }
            }
        }
        return list;
    }

    public List<ShareholderBuyGrantHistory> getByUserIdAndNotInExistGrantHistory(int userId, int grantId) {
        CommonExample example = new CommonExample(ShareholderBuyGrantHistory.class);
        example.equals("userId", userId);
        Example.Criteria criteria = example.getCriteria();
        criteria.andLessThan("grantId", grantId);
        return getsByExampleWithoutComplete(example);
    }

    public BigDecimal getTotalGrantCount(int userId, int coinTypeId) {
        BigDecimal totalGrantCount = new BigDecimal(0);
        List<ShareholderCoinGrantHistory> shareholderCoinGrantHistoryList1 = shareholderCoinGrantHistoryService.getsByUserIdAndCoinTypeWithoutRemove(userId, coinTypeId);
        int lowestGrantId = 0;
        if (shareholderCoinGrantHistoryList1 != null && !shareholderCoinGrantHistoryList1.isEmpty()) {
            for (ShareholderCoinGrantHistory shareholderCoinGrantHistory : shareholderCoinGrantHistoryList1) {
                totalGrantCount = totalGrantCount.add(shareholderCoinGrantHistory.getCount());
            }
            lowestGrantId = shareholderCoinGrantHistoryList1.get(shareholderCoinGrantHistoryList1.size() - 1).getId();
        }
        if (lowestGrantId != 0) {
            List<ShareholderBuyGrantHistory> shareholderBuyGrantHistories = this.getByUserIdAndNotInExistGrantHistory(userId, lowestGrantId);
            if (shareholderBuyGrantHistories != null && !shareholderBuyGrantHistories.isEmpty()) {
                for (ShareholderBuyGrantHistory shareholderBuyGrantHistory : shareholderBuyGrantHistories) {
                    totalGrantCount = totalGrantCount.add(shareholderBuyGrantHistory.getCount());
                }
            }
        }
        return totalGrantCount;
    }

}
